﻿#include<conio.h>
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
#include<mmsystem.h>
#include<iostream>
#include<fstream>
#include<time.h>
#include<string>
#include<vector>
#include"Game.h"

int main()
{	
	while(true)	
	{		   
		clearScreen();		
		int n=0;			
		printf("1.开始游戏\n2.退出游戏\n");			
		scanf_s("%d",&n, 1);	
		switch(n)			
		{			
			case 1:				
				clearScreen();
				textout(map_posX + 20, map_posY + 1, "Select Level：");				
				textout(map_posX + 20, map_posY + 3, "Level 1");						
				while(true)				
				{										
					char choice;					
					choice=_getch();					
					if(choice=='1')					
					{					
						clearScreen();
						textout(map_posX + 20, map_posY, "开始游戏");														
						Sleep(2000);						
						break;					
					}					
					else if(choice!='1')				
						continue;			
				}

				Game_Run();				
				break;			
			case 2:				
				return 0;			
			default:				
				printf("错误，重新选择");	
				Sleep(1000);
		}	
	}
}

void Game_Run()
{
	clearScreen();
	load_Map();
	draw_Map();
	cActor ca(15, 18, typeTank, KEY_UP);
	cv.push_back(ca);
	ca.draw();
	while(true)
	{
		for(std::vector<cActor>::size_type st = 0; st != cv.size(); st++)
		{
			if(!cv[st].hasFlag(hidden))
			{
				cv[st].update();
			}
		}
		frame++;
	}

}

void cActor::update()
{
	delete_cache();	
	int key = -1;
	int delay = 0, maxDelay = 200;
	switch(type)
	{
		case typeTank:
			while(delay < maxDelay)
			{
				if(_kbhit())			
				{					
					key=_getch(); 
				}	
				delay++;
			}
			if(isDirKey(key))
			{
				direction = key;
			}
			if(key == KEY_ESC)
			{
				exit(EXIT_SUCCESS);  	
			}
			else if(key == KEY_S)
			{
				shot();
			}
			else if(canMove(key))
			{
				move(key);
				draw();
			}		
			break;
		case typeBullet:
			if(frame % 20 != 0)
				break;

			if(map[pos_y * map_w + pos_x] == -2)
			{
				addFlag(hidden);
				break;
			}

			delete_blocks(pos_x,pos_y);
			if(map[pos_y * map_w + pos_x] == -1)
			{
				map[pos_y * map_w + pos_x] = 0;
				addFlag(hidden);
				break;
			}

			if(direction == KEY_UP)
			{
				pos_y--;
			}
			else if(direction == KEY_DOWN)
			{
				pos_y++;
			}
			else if(direction == KEY_LEFT)
			{
				pos_x--;
			}
			else if(direction == KEY_RIGHT)
			{
				pos_x++;
			}

			draw();
			break;
	}	
}


//坦克移动
void cActor::move(int dir)
{
	delete_blocks(pos_x,pos_y);
	switch(direction)
	{
		case KEY_UP:
			pos_y--;
			break;
		case KEY_DOWN:
			pos_y++;
			break;
		case KEY_LEFT:
			pos_x--;
			break;
		case KEY_RIGHT:
			pos_x++;	
			break;
	}
}

//判断坦克是否可以移动
bool cActor::canMove(int dir)
{
	int x = pos_x;
	int y = pos_y;
	switch(dir)
	{
		case KEY_UP:
			y -= 1;
			break;
		case KEY_DOWN:
			y += 1;
			break;
		case KEY_LEFT:
			x -= 1;
			break;
		case  KEY_RIGHT:
			x += 1;
			break;
		default:
			return false;
	}
	return map[y * map_w + x] != -1 && map[y * map_w + x] != -2;
}

//画图
void cActor::draw()
{
	int needDraw = 1;
	if(pos_x <= 0)
	{
		pos_x = 0;
		needDraw = 0;
	}
	else if(pos_x >= 38)
	{
		pos_x = 38;
		needDraw = 0;
	}
			
	if(pos_y <= 0)
	{
		pos_y = 0;
		needDraw = 0;
	}
	else if(pos_y >= 19)
	{
		pos_y = 19;
		needDraw = 0;
	}
				
	if(!needDraw)
		return;

	if(type == typeTank)
	{
		textout(2 * pos_x + map_posY,pos_y + map_posY,"¤");
	}
	else if(type == typeBullet)
	{
		textout(2 * pos_x + map_posX,pos_y + map_posY,"☉");
	}
}

//删除坦克
void cActor::delete_blocks(int x,int y) 
{
	textout(2 * x + map_posX,y + map_posY,"  ");
}

//射击
void cActor::shot()
{	
	int posX = pos_x;
	int posY = pos_y;

	switch(direction)
	{
		case KEY_UP:
			posY--;
			break;
		case KEY_DOWN:
			posY++;
			break;
		case KEY_LEFT:
			posX--;
			break;
		case KEY_RIGHT:
			posX++;
			break;
	}
	cActor bullet(posX, posY, typeBullet, direction);
	cv.push_back(bullet);
	bullet.draw();
}

void cActor::addFlag(int value)
{
	flag |= value;
}

void cActor::removeFlag(int value)
{
	flag &= (~value);
}

bool cActor::hasFlag(int value)
{
	return (flag & value) != 0;
}

//画地图
void draw_Map()
{
	drawblocks(map,map_w,map_h,0,0);
}

//画墙
void drawblocks(int a[],int w,int h,int x,int y)
{		

	for(int i=0;i<h;i++)
	{
		for(int j=0;j<w;j++)	
		{
			if(map[i*map_w+j] < 0)
			{
				textout(2 * (x + j) + map_posX, y + i + map_posY, "=");					
			}
			else if(map[i*map_w+j] == 2)
			{
				textout(2 * (x + j) + map_posX, y + i + map_posY, "★");
			}
		}
	}
}

void delete_cache() 
{	
	while(_kbhit())	
	{		
		_getch();	
	}
}

HANDLE initiate()
{	
	HANDLE hOutput; 	
	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);	
	return hOutput;
}

BOOL textout(int x, int y, LPTSTR lpszString)
{   
	HANDLE handle;	
	handle=initiate();

	DWORD cWritten;    
	BOOL fSuccess;     
	COORD coord;    	
	coord.X = x;            
	coord.Y = y;       
	fSuccess = WriteConsoleOutputCharacter(         
		handle,   
		lpszString,       
		lstrlen(lpszString),
		coord,      
		&cWritten); 

	if (! fSuccess)        
		std::cout<<"error:WriteConsoleOutputCharacter"<<std::endl;

	return 0;
}

void clearScreen()
{
	system("CLS");
}

//加载地图
void load_Map()
{
	std::string fileName = "Map\\map_level1.txt";
	std::ifstream ism(fileName.c_str());

	int width,height;
	ism >> width;
	ism >> height;

	map_w = width;
	map_h = height;

	int *map_temp = new int[width * height];
	for(int index = 0;index != (width * height);index++)
	{
		ism >> *(map_temp + index);
	}

	ism.close();
	if(ism.eof())
	{
		std::cerr << "地图加载成功！" << std::endl;
	}
	else if(ism.bad())
	{
		std::cerr << "Error：加载地图时发生系统级故障！" << std::endl;
	}
	else if(ism.fail())
	{
		std::cerr << "Error：读取地图数据失败！" << std::endl;
	}

	map = map_temp;
}

boolean isDirKey(int key)
{
	return key == KEY_UP || key == KEY_DOWN || key == KEY_LEFT || key == KEY_RIGHT;
}